#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QNetworkDatagram>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 更改窗口标题区分客户端和服务器
    this->setWindowTitle("服务器");
    // 构造server对象
    server = new QUdpSocket(this);
    // 一定是先关联信号槽再绑定端口号！
    // 因为读取数据是通过信号readyRead来触发的
    // 如果先绑定，再关联信号槽。 在绑定和关联信号槽之间
    // 客户端是可以连接的，此时就会收不到数据，造成丢包
    // 因此必须要先关联信号槽

    // 1.关联信号槽-readyRead
    connect(server,&QUdpSocket::readyRead,this,&Widget::processRequest);

    // 2.绑定端口号
    // Any: 让os随机绑定本机网卡中任意一个ip
    bool ret = server->bind(QHostAddress::Any,8888);
    if(!ret)
    {
        // errorString 显示
        QMessageBox::critical(this,"错误",server->errorString());
    }

}

// 当客户端发来消息后触发信号,就会执行对应的槽函数processRequest
// 处理请求
void Widget::processRequest()
{
    // 1.获取请求数据报并解析
    const QNetworkDatagram& requestDatagram = server->receiveDatagram();
    // data 返回的是QByteArray类型的数据
    // QString 此类型的赋值重载
    QString req = requestDatagram.data();
    // 2.根据请求计算响应
    // 因为此处是回显服务器，我不用处理请求
    QString resp = process(req);
    // 3.把响应写回客户端
    // 构造数据报
    QNetworkDatagram respDatagram(resp.toUtf8(),requestDatagram.senderAddress(),requestDatagram.senderPort());
    server->writeDatagram(respDatagram);
    // 4.将这次交互的信息显示在ListWidget上
    QString log = "[" + requestDatagram.senderAddress().toString() +  ":" + QString::number(requestDatagram.senderPort())
                  + "] request: " + req + "  response: " + resp;
    ui->listWidget->addItem(log);

}

QString Widget::process(QString req)
{
    return req;
}


Widget::~Widget()
{
    delete ui;
}




